//
// Created by yanhai on 2020/2/18.
//

#include <iostream>

using namespace std;

/**
 *  auto关键字
 *      C++11新标准就引入了类型自动推断：auto关键字让编译器通过初始值
 *      来进行类型推导。从而获得定义变量的类型，auto定义的变量必须有初始值。
 *
 *  decltype关键字
 *      C++11新标准编译时类型推导，除了auto关键字，还有decltype关键字，
 *      decltype不是像auto一样是从变量的初始化表达式获得类型，而是以表达式作为参数，
 *      返回该表达式的类型，并且decltype不会对表达式求值。
 *
 *  typeid关键字
 *      介绍参考<https://blog.csdn.net/xuqingict/article/details/25003713>，写的不错
*/
void test1()
{
    auto a = 100;
    cout << typeid(a).name() << endl;   // i

    auto b = 1.243f;
    cout << typeid(b).name() << endl;   // f

    decltype(a++) c;    // 不会对a++操作
    cout << a << ", " << typeid(c).name() << endl;   // 100, i

    decltype('a') d;
    cout << typeid(d).name() << endl;   // c

    decltype(&c) e;
    cout << typeid(e).name() << endl;   // Pi
}

/**
 * - 当不清楚函数返回值类型时，可以使用auto
 * - auto做函数返回值类型时必须配合decltype使用
 * - auto不可以做形参类型
 * @param a
 * @param b
 * @return
 */
auto add(int a, float b) -> decltype(a + b)
{
    cout << "add function" << endl;
    return a + b;
}

// 或者模板函数时
template<typename T1, typename T2>
auto add(const T1 &t1, const T2 &t2) -> decltype(t1 + t2)
{
    cout << "template add function" << endl;
    return t1 + t2;
}

void test2()
{
    auto c = add(10, 2.3f); // 调用 add 函数
    cout << c << ", " << typeid(c).name() << endl;  // 12.3, f

    auto d = add(10.2, 'c');    // 调用 add 模板函数
    cout << d << ", " << typeid(d).name() << endl;  // 109.2, d
}

int main()
{
    test1();
    test2();
    return 0;
}
